package com.clippick.api;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.SystemClock;
import android.util.Log;

import com.clippick.common.GlobalValue;
import com.clippick.network.SocketIOClient;

public class GetApi {
	public static interface Handler {
		public void onSocketMessage(JSONArray result);
	}

	// common
	private Context mContext;
	private SharedPreferences pref;
	private Editor editor;
	private Handler mHandler;
	private SocketIOClient.Handler listener;

	// server
	private SocketIOClient client;

	// sharedPrefereces 사용할떄
	public GetApi(Context context) {
		mContext = context;
		pref = mContext.getSharedPreferences(GlobalValue.KEY,
				Context.MODE_PRIVATE);
		editor = context.getSharedPreferences(GlobalValue.KEY,
				Context.MODE_PRIVATE).edit();
	}

	// sharedPrefereces 사용 안할때
	public GetApi() {

	}

	public SocketIOClient.Handler getListener() {
		return listener;
	}

	public String signUpWithoutName(String email, String password) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("email", email);
		params.put("password", password);
		GetDataFromApi.TYPE = "POST";
		return GetDataFromApi.getRaw(GetDataFromApi.API_NODEJS_SIGN_UP, params);
	}

	public String loginWithFacebook(String uuid, String email) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("email", email);
		params.put("fb_uid", uuid);
		GetDataFromApi.TYPE = "POST";
		return GetDataFromApi.getRaw("facebook_proc.php", params);
	}

	public String sendPing() {
		Map<String, String> params = new HashMap<String, String>();
		GetDataFromApi.TYPE = "GET";
		return GetDataFromApi.getRaw(GetDataFromApi.API_NODEJS_PING, params);
	}

	public void connectSocket() {
		listener = new SocketIOClient.Handler() {
			public void onError(Exception error) {
				Log.d("socket", "" + error);
			}

			public void onDisconnect(int code, String reason) {
				// TODO Auto-generated method stub
				Log.d("socket", String.format(
						"Disconnected! Code: %d Reason: %s", code, reason));
			}

			public void onConnect() {
				// TODO Auto-generated method stub
				Log.d("socket", "Connected!");
			}

			public void on(String event, JSONArray arguments) {
				// TODO Auto-generated method stub
				Log.i("socket", "event : " + event);
				if (event.toString().contains("giveme")) {
					Log.i("socket", "start another tcp protocol");
					sendSocketMessage();
				} else if (event.toString().contains("newevent")) {
					try {
						JSONArray array = new JSONArray(arguments.toString());
						JSONObject data = array.getJSONObject(0);
						JSONArray result = data.getJSONArray("data");
						mHandler.onSocketMessage(result);

						for (int i = 0; i < result.length(); i++) {
							String no = result.getJSONObject(i).getString("NO");
							String star = result.getJSONObject(i).getString(
									"B_KEEP");
							Log.d("result", "NO : " + no + " STAR : " + star);
						}

					} catch (Exception e) {
						e.printStackTrace();
					}

				}
				Log.d("socket",
						String.format("Got event %s: %s", event,
								arguments.toString()));
			}
		};

		client = new SocketIOClient(URI.create("http://clippick.com:8124"),
				listener);

		client.connect();
	}

	private void sendSocketMessage() {
		String email = pref.getString("UserID", "");
		String key = pref.getString("REGISTRATION_KEY", "");
		String time = GlobalValue.UPDATE_TIME;
		try {
			JSONArray arguments = new JSONArray();
			JSONObject second = new JSONObject();
			second.put("email", email);
			second.put("reg_key", key);
			second.put("up_time", time);
			arguments.put(second);

			client.emit("clippick-params", arguments);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public JSONArray getFeedResult() {
		return null;
	}

	public String forgotPasswordApi(String email) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("email", email);
		GetDataFromApi.TYPE = "GET";
		String jsonData = GetDataFromApi.getRaw("forgot_password.php", params);
		String result = jsonData;
		return result;
	}

	public String inviteTinyUrlApi() {
		String result = "";
		try {
			String url = GetDataFromApi.INVITE_URL + GlobalValue.USER_ID;

			HttpClient client = new DefaultHttpClient();

			try {
				HttpGet request = new HttpGet();
				request.setURI(new URI(url));
				// Log.d("api", "uri=" + url);

				HttpResponse response = client.execute(request);
				BufferedReader in = new BufferedReader(new InputStreamReader(
						response.getEntity().getContent()));

				String tempStr = "";
				StringBuilder htmlSource = new StringBuilder();

				while ((tempStr = in.readLine()) != null) {
					htmlSource.append(tempStr);
				}

				in.close();

				result = htmlSource.toString();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (URISyntaxException e1) {
				e1.printStackTrace();
			} finally {
				client.getConnectionManager().shutdown();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	public boolean sendFeedback(String feel, String os, String comment) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("lv", feel);
		params.put("Device", os);
		params.put("comment", comment);
		GetDataFromApi.TYPE = "POST";
		String jsonData = GetDataFromApi.getRaw("feedback_new.php", params);
		Map<String, String> objects = getJsonObjectIterator(jsonData);

		return objects.get("returnCode").equals("200") ? true : false;
	}

	// login Api
	public Map<String, String> loginApi(String userEmail, String userPass) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("UserID", userEmail);
		params.put("PW", userPass);
		params.put("RegistrationID", "a"); // C2DM은 사용하지 않기 때문에 put fake value.
		GetDataFromApi.TYPE = "POST";
		String jsonData = GetDataFromApi.getRaw("doLogin_new.php", params);

		Map<String, String> result = getJsonObjectIterator(jsonData);
		Log.d("api", "login : " + jsonData);

		return result;

		// sharedPreferences 에 로그인 정보 저장
		// try {
		// String success = result.get("returnCode").toString();
		// if (success.equals("200")) {
		// pref.edit().putString("REGISTRATION_KEY",
		// result.get("REGISTRATION_KEY").toString());
		// editor.putString("UserID", userEmail);
		// editor.putString("PW", userPass);
		// editor.commit();
		// Log.i("login", result.toString());
		// GlobalValue.USER_ID = userEmail;
		// GlobalValue.USER_KEY = pref.getString("REGISTRATION_KEY", "");
		// GlobalValue.UPDATE_TIME = result.get("UPDATE_TIME").toString();
		// return true;
		// }
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
		// return false;
	}

	// join Api
	public String joinApi(String userEmail, String userPass, String userName1,
			String userName2) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("fn", userName1);
		params.put("ln", userName2);
		params.put("id", userEmail);
		params.put("pw", userPass);
		GetDataFromApi.TYPE = "POST";
		String jsonData = GetDataFromApi.getRaw("sign_upload_interface.php",
				params);
		String result = jsonData;
		return result;
	}

	/**
	 * @param json
	 * @return
	 */
	public Map<String, String> getJsonObjectIterator(String json) {
		Map result = new HashMap<String, String>();
		try {
			JSONObject object = new JSONObject(json);
			String success = object.getString("returnCode");
			Iterator itr = object.keys();
			while (itr.hasNext()) {
				Object key = itr.next();
				Log.d("json",
						"key : " + key + ", value : "
								+ object.get((String) key));
				result.put(key, object.get((String) key));
				if (key.equals("REGISTRATION_KEY")) {
					editor.putString("REGISTRATION_KEY",
							object.get((String) key).toString());
					editor.commit();
				}
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * @param json
	 * @return {count=?, max=?}
	 */
	public Map<String, String> getStarDataFromJSON(String json) {
		Map result = new HashMap<String, String>();
		try {
			JSONObject object = new JSONObject(json);
			String max = object.getString("Max_Star");
			String count = object.getString("Star_Count");
			result.put("max", max);
			result.put("count", count);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	// sync check
	/**
	 * @param REGISTRATION_KEY
	 * @param UserID
	 * @return JSON {"returnType": "syncCheck","returnCode":
	 *         "200","returnMessage": "성공" ,"Feeds":[{"NO":"1617","B_KEEP":"0"}
	 */
	public List<Map> checkFeedsSync() {
		List<Map> result = new ArrayList<Map>();
		GlobalValue.USER_ID = pref.getString("UserID", "");
		GlobalValue.USER_KEY = pref.getString("REGISTRATION_KEY", "");

		Map<String, String> params = new HashMap<String, String>();
		params.put("REGISTRATION_KEY", pref.getString("REGISTRATION_KEY", ""));
		params.put("UserID", pref.getString("UserID", ""));

		GetDataFromApi.TYPE = "POST";
		result = GetDataFromApi.getData(GetDataFromApi.API_SYNC_CHECK, params);
		return result;
	}

	public String longPolling(String clientTime, String userId, String regKey) {
		GlobalValue.USER_ID = pref.getString("UserID", "");
		GlobalValue.USER_KEY = pref.getString("REGISTRATION_KEY", "");

		Map<String, String> params = new HashMap<String, String>();
		params.put("email", GlobalValue.USER_ID);
		params.put("regkey", GlobalValue.USER_KEY);
		params.put("uptime", clientTime);

		Log.i("longpoll", "request params : " + params.toString());

		GetDataFromApi.TYPE = "POST";
		return GetDataFromApi.getRaw(GetDataFromApi.API_NODEJS_LONG_POLLING, params);
	}

	public String checkSyncTime() {
		String result = "";
		GlobalValue.USER_ID = pref.getString("UserID", "");
		GlobalValue.USER_KEY = pref.getString("REGISTRATION_KEY", "");

		Map<String, String> params = new HashMap<String, String>();
		params.put("REGISTRATION_KEY", pref.getString("REGISTRATION_KEY", ""));
		params.put("UserID", pref.getString("UserID", ""));

		GetDataFromApi.TYPE = "POST";
		result = GetDataFromApi.getRaw(GetDataFromApi.API_SYNC_CHECK_TIME,
				params);
		// Log.i("syncCheck2", result);
		return result;
	}

	/*
	 * memoValue "1" is for normal copy
	 * memoValue "2" is for clip from typing
	 * */
	public String insertNodeNewClip(String content, String memoValue) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("UserID", GlobalValue.USER_ID);
		params.put("device", "android");
		params.put("content", content);
		params.put("REGISTRATION_KEY", GlobalValue.USER_KEY);

		GetDataFromApi.TYPE = "POST";
		String jsonData = GetDataFromApi.getRaw(
				GetDataFromApi.API_NODEJS_INSERT, params);

		String result = "";
		Map<String, String> data = new HashMap<String, String>();
		data = getJsonObjectIterator(jsonData);
		result = data.get("returnCode").toString();
		return result;
	}

	// insert text data
	public String insertNewClip(String content, String memoValue) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("UserID", GlobalValue.USER_ID);
		params.put("device", "android");
		params.put("is_memo", memoValue);
		params.put("content", content);
		params.put("REGISTRATION_KEY", GlobalValue.USER_KEY);

		GetDataFromApi.TYPE = "POST";
		String jsonData = GetDataFromApi.getRaw(GetDataFromApi.API_INSERT,
				params);

		String result = "";
		Map<String, String> data = new HashMap<String, String>();
		data = getJsonObjectIterator(jsonData);
		result = data.get("returnCode").toString();
		return result;
	}

	// insert image data
	public String insertImageClip(byte[] fileByte) throws Exception {
		String result = "";
		try {
			String imageName = GlobalValue.USER_ID + "_"
					+ System.currentTimeMillis();

			HttpClient httpClient = new DefaultHttpClient();
			HttpPost postRequest = new HttpPost(GetDataFromApi.SERVER
					+ GetDataFromApi.API_INSERT_IMAGE);
			
//			Log.d("api", GetDataFromApi.IMAGE_SERVER + GetDataFromApi.API_NODEJS_INSERT);

			ByteArrayBody bab = new ByteArrayBody(fileByte, "image"
					+ System.currentTimeMillis() + ".jpg");

			MultipartEntity reqEntity = new MultipartEntity(
					HttpMultipartMode.BROWSER_COMPATIBLE);
			reqEntity.addPart("UserID", new StringBody(GlobalValue.USER_ID));
			reqEntity.addPart("device", new StringBody("Android"));
			reqEntity.addPart("REGISTRATION_KEY", new StringBody(
					GlobalValue.getUserRegistrationKey(mContext)));
			reqEntity.addPart("image", bab);
			postRequest.setEntity(reqEntity);

			final HttpResponse response = httpClient.execute(postRequest);

			BufferedReader reader = new BufferedReader(new InputStreamReader(
					response.getEntity().getContent(), "UTF-8"));

			String sResponse;
			s = new StringBuilder();

			while ((sResponse = reader.readLine()) != null) {
				s = s.append(sResponse);
			}

			Log.d("api", "respons=" + s.toString());

		} catch (Exception e) {
			Log.e(e.getClass().getName(), e.getMessage());
			e.printStackTrace();
		}

		return result;
	}

	int percentage = 0;
	StringBuilder s;

	// get data
	public List<Map> getnewClip(String idx) {
		Log.i("api", "get data (" + idx + ")");
		Map<String, String> params = new HashMap<String, String>();
		params.put("UserID", pref.getString("UserID", "magicdo7@gmail.com"));
		params.put("REGISTRATION_KEY", GlobalValue.USER_KEY);
		params.put("idx", idx);

		GetDataFromApi.TYPE = "POST";

		List<Map> result = GetDataFromApi.getData(GetDataFromApi.API_GET_FEEDS,
				params);
		Log.i("geeFeeds", result + "");

		// 재정의된 데이터
		// result = ClipData.getClipData(result);

		return result;
	}

	// delete data
	public boolean deleteClipApi(String index) {
		boolean result = false;
		Map<String, String> params = new HashMap<String, String>();
		params.put("UserID", GlobalValue.USER_ID);
		params.put("REGISTRATION_KEY", GlobalValue.USER_KEY);
		params.put("idx", index);

		GetDataFromApi.TYPE = "POST";
		String json = GetDataFromApi.getRaw(GetDataFromApi.API_DELETE, params);
		Map<String, String> data = getJsonObjectIterator(json);
		if (data.get("returnCode").toString().equals("200")) {
			result = true;
		}

		return result;
	}

	// star
	public Map<String, String> setStarApi(String idx, String starValue) {
		Map<String, String> result = new HashMap<String, String>();
		Map<String, String> params = new HashMap<String, String>();
		params.put("UserID", GlobalValue.USER_ID);
		params.put("REGISTRATION_KEY", GlobalValue.USER_KEY);
		params.put("B_KEEP", starValue);
		params.put("idx", idx);

		GetDataFromApi.TYPE = "POST";
		String json = GetDataFromApi.getRaw(GetDataFromApi.API_CHANGE, params);
		result = getJsonObjectIterator(json);
		// if (data.get("returnCode").toString().equals("200")) {
		// result = true;
		// }

		return result;
	}
}
